/**
 * Copyright (c) 2006-2020, zwl
 * 
 * description  控制台
 * 
 * Change Logs:
 * Date             Author         Notes
 * 2019-03-15       zwl             [0.0.1]第一版本实现控制台与slog
 * 2019-03-20       zwl             [0.0.2]修改命令行接收为一维数组
 * 2019-03-21       zwl             [0.1.3]修改命令行串口接收为FIFO方式
 * 2019-03-22       zwl             [1.0.0]修改tab补全功能，增加补全列表显示
 */

//#include "stdio.h"
//#include "stdlib.h"
#include "string.h"
//#include "main.h"
#include "EntTypeFramework.h"
#include "Bsp.h"
#include "console.h"

#if	USE_CONSOLE_UART

/* *--------------------------宏定义--------------------------* */
#define CONSOLE_EVENT_RX_DONE                         0x00000001

typedef struct{
    con_cmd_in                  ConCmdIn[CONFIG_CONSOLE_CMD_HISTORY_NUM];
    etf_uint8_t                 Index;
    etf_uint8_t                 Top;
}con_cmd_in_history;

/* *-------------------------函数声明-------------------------* */
void console_RxChAnalysis(etf_device_t Device, void *paraemeter);
void ComCmd_CmdLine(char *str);
etf_int32_t ConCmd_Pro(con_cmd_in *pConCmdIn);

etf_int32_t ConCmd_Versions(etf_int32_t argc, con_cmd_analysis *argv);
etf_int32_t ConCmd_Help(etf_int32_t argc, con_cmd_analysis *argv);
etf_int32_t ConCmd_Reboot(etf_int32_t argc, con_cmd_analysis *argv);
etf_int32_t ConCmd_DeviceList(etf_int32_t argc, con_cmd_analysis *argv);
etf_int32_t ConCmd_EventList(etf_int32_t argc, con_cmd_analysis *argv);
etf_int32_t ConCmd_TimerList(etf_int32_t argc, con_cmd_analysis *argv);
etf_int32_t ConCmd_CoroutineList(etf_int32_t argc, con_cmd_analysis *argv);

/* *-------------------------指令列表-------------------------* */
/* CPU重启指令 */
const con_cmd                         ConCmdReboot                = {
    .Cmd                                                    = "reboot",
    .DesStr                                                 = "The software restarts the CPU.\r\n",
    .Fun                                                    = ConCmd_Reboot
};

/* 版本输出指令 */
const con_cmd                         ConCmdVersion               = {
    .Cmd                                                    = "version",
    .DesStr                                                 = "Print out version information.\r\n",
    .Fun                                                    = ConCmd_Versions
};

/* 帮助信息 */
const con_cmd                         ConCmdHelp                  = {
    .Cmd                                                    = "help",
    .DesStr                                                 = "Print out a list of instructions.\r\n",
    .Fun                                                    = ConCmd_Help
};

/* 设备信息 */
const con_cmd                         ConCmdDevice                = {
    .Cmd                                                    = "device_list",
    .DesStr                                                 = "Print out a list of device.\r\n",
    .Fun                                                    = ConCmd_DeviceList
};

/* 事件信息 */
const con_cmd                         ConCmdEvent                 = {
    .Cmd                                                    = "event_list",
    .DesStr                                                 = "Print out a list of event.\r\n",
    .Fun                                                    = ConCmd_EventList
};

/* 定时器信息 */
const con_cmd                         ConCmdTimer                 = {
    .Cmd                                                    = "timer_list",
    .DesStr                                                 = "Print out a list of timer.\r\n",
    .Fun                                                    = ConCmd_TimerList
};

/* 协程信息 */
const con_cmd                         ConCmdCoroutine             = {
    .Cmd                                                    = "ps",
    .DesStr                                                 = "Print out a list of coroutine.\r\n",
    .Fun                                                    = ConCmd_CoroutineList
};


//int fputc(int ch,FILE *f);

/* *-------------------------全局变量-------------------------* */
static con_cmd_analysis         AnalysisCmd;

/* 控制台设备句柄 */
etf_device_t					ConsoleDevHanld             = ETF_NULL;
/* 输入指令控制与存放结构 */
con_cmd_in                      ConCmdIn;
/* 历史指令控制与存放结构 */
con_cmd_in_history              ConCmdInHistory;

/* 版本信息 */
char ConsoleVersion[]                                       = {"\r\n\033[40;32m\
   ***\r\n\
 **                   Use EntTypeFramework\r\n\
**  C     Event - driven coroutine framework program\r\n\
 **              - - - - - - - - - - - - - - - -\r\n\
   ***    Customize the simple console(1.0.0) - ZhangWL\033[0m\r\n\
"};

/* 接收数据完成事件 */
static etf_event_ev_t           ConsoleEvent;
/* 控制台串口设备接收到新数据事件 */
static etf_event_ev_t           ConsoleRxDeviceEvent;
/* 控制[控制台串口设备接收到新数据事件]事件产生频率，读取空串口缓冲区后，清零事件，允许接收中断投递事件 */
static etf_uint8_t              ConsoleRxDevicePostFlag     = 0;

extern con_cmd *                ConCmdTable[];

etf_err_t console_rx_indicate(etf_device_t dev, etf_size_t size);

/* *-------------------------实例定义-------------------------* */


/**
 *  定义控制台处理进程
 *
 *@param :
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
ETF_PROCESS(console_ps, co_ev, co_data){

    ETF_PROCESS_BEGIN();

    memset(&ConCmdIn, 0, sizeof(ConCmdIn));
    memset(&ConCmdInHistory, 0, sizeof(ConCmdInHistory));
  
    /* 初始化事件,用于数据接收完成产生的中断 */
    ConsoleEvent                                            = etf_event_alloc();
    /* 查找设备，用于控制台输入输出 */
    ConsoleDevHanld                                         = etf_device_find("debug");

    /* 打开设备 */
    etf_device_open(ConsoleDevHanld, ETF_DEVICE_FLAG_WRONLY);
    /* 配置设备 */
    etf_device_set_rx_indicate(ConsoleDevHanld, console_rx_indicate);
	/* 设置串口波特率 */
	etf_device_control(ConsoleDevHanld, DEBUG_CTRL_CMD_BAUDRATE, (void *)CONFIG_CONSOLE_CMD_BAUD);

    /* 打印版本信息 */
    ConCmd_Versions(0, NULL);
    /* 打印控制行提示信息 */
    ComCmd_CmdLine("cmd>>");
  
    while (1){
        /* 等待接收完成事件 */
        ETF_PROCESS_WAIT_EVENT_UNTIL(co_ev == ConsoleEvent);

        if(CONSOLE_EVENT_RX_DONE == (((etf_uint32_t)co_data)&CONSOLE_EVENT_RX_DONE)){
            /* 处理接收完成事件 */
            ConCmd_Pro(&ConCmdIn);
        }
    }

    ETF_PROCESS_END();
}

/**
 *  定义控制台循环接收
 *
 *@param :
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
ETF_PROCESS(console_rx_ps, co_ev, co_data){

    ETF_PROCESS_BEGIN();

    static etf_uint8_t          rx_buffer[CONFIG_DEBUG_RX_BUFFER_SIZE], length = 0, index;
//    static struct etf_timer     rx_timer;
    /* 初始化事件,用于控制台串口设备接收到新数据产生的中断 */
    ConsoleRxDeviceEvent                                    = etf_event_alloc();
    
    while(1){

//        etf_delayms((&rx_timer), 10);
        /* 等待接事件 */
        ETF_PROCESS_WAIT_EVENT_UNTIL(co_ev == ConsoleRxDeviceEvent);
again:
        do{
            /* 处理数据，默认length=0，上次取出完成后length=0，所以第一次不会进入 */
            for(index = 0; index < length; index++){
                console_RxChAnalysis(ConsoleDevHanld, (void *)&(rx_buffer[index]));
            }
            /* 读数据 */
            length                                          = etf_device_read(ConsoleDevHanld, 0, (void *)rx_buffer, CONFIG_DEBUG_RX_BUFFER_SIZE);
        }while(length);
        /* 读取完成，清标志 */
        ConsoleRxDevicePostFlag                             = 0;
        /* 确认是否读取完成 */
        length                                              = etf_device_read(ConsoleDevHanld, 0, (void *)rx_buffer, CONFIG_DEBUG_RX_BUFFER_SIZE);
        if(0 != length){
            /* 在判断读取完成，并清除ConsoleRxDevicePostFlag标志的过程中是否又产生新的数据，产生后，返回循环执行 */
            goto again;
        }
    }
  ETF_PROCESS_END();
}

/**
 *  leds协程初始化
 *
 *@param :
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
/* 定义控制处理协程控制块 */
struct etf_co_tcb               console_ps;
/* 定义控制处理协程控制块 */
struct etf_co_tcb               console_rx_ps;
etf_err_t console_ps_init(void){
    etf_coroutine_init(&console_ps, "console_ps", ETF_PROCESS_NAME_GET(console_ps));
    etf_coroutine_startup(&console_ps);

    etf_coroutine_init(&console_rx_ps, "console_rx_ps", ETF_PROCESS_NAME_GET(console_rx_ps));
    etf_coroutine_startup(&console_rx_ps);

    return ETF_EOK;
}

/**
 *  控制台串口设备，接收中断
 *
 *@param :  dev ：设备；
 *          size：数据尺寸；
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
etf_err_t console_rx_indicate(etf_device_t dev, etf_size_t size){

    if(0 == ConsoleRxDevicePostFlag){
        ConsoleRxDevicePostFlag                             = 1;
        etf_event_post(&console_rx_ps, ConsoleRxDeviceEvent, ETF_NULL);
    }

    return ETF_EOK;
}

/**
 *  接收数据分析处理
 *
 *@param :  Device      ：设备指针；
 *          paraemeter  ：输入的数据；
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
void console_RxChAnalysis(etf_device_t Device, void *paraemeter){

    char                        para                        = *((char *)paraemeter);
    etf_uint8_t                 print_flag                  = 0;                    /* 回显标志 */

    if(ETF_SET == ConCmdIn.Lock){
        /* 命令未处理锁定状态输入无效 */
        return;
    }

    if( (CMD_IN_ARR_SIZE > ConCmdIn.LastIndex) && (0 == ConCmdIn.CombinationCount) ){
        ConCmdIn.CmdIn[ConCmdIn.LastIndex]                  = para;
    }

    if('\n' == para) {//-----------------------------处理\n
        /* 以\n输入结束，补充\r输出 */
        etf_device_write(Device, 0, (void *)"\r\n", 2);

        ConCmdIn.CmdIn[ConCmdIn.LastIndex]                  = '\0';
        ConCmdIn.Lock                                       = ETF_SET;
        if((CON_CMD_NO_ERR != ConCmdIn.Sta) && (CON_CMD_PARA_ERR != ConCmdIn.Sta) ){
            ConCmdIn.Sta                                    = CON_CMD_NO_ERR;
        }
        /* 输入完成事件 */
        etf_event_post(&console_ps, ConsoleEvent, (void *)CONSOLE_EVENT_RX_DONE);

    } else if('\r' == para) {//-----------------------------处理\r
        /* 以\r输入结束，补充\n输出 */
        etf_device_write(Device, 0, (void *)"\r\n", 2);

        ConCmdIn.CmdIn[ConCmdIn.LastIndex]                  = '\0';
        ConCmdIn.Lock                                       = ETF_SET;
        if((CON_CMD_NO_ERR != ConCmdIn.Sta) && (CON_CMD_PARA_ERR != ConCmdIn.Sta) ){
            ConCmdIn.Sta                                    = CON_CMD_NO_ERR;
        }
        /* 输入完成事件 */
        etf_event_post(&console_ps, ConsoleEvent, (void *)CONSOLE_EVENT_RX_DONE);
    } else if('\b' == para){//-----------------------------处理\b
        if(0 != ConCmdIn.LastIndex){
            etf_device_write(Device, 0, (void *)"\b \b", 3);
            ConCmdIn.LastIndex--;
            if(0 != ConCmdIn.Index){
                ConCmdIn.Index--;
            }
        }

    } else if('\t' == para){//-----------------------------处理\t
        ConCmdIn.CmdIn[ConCmdIn.LastIndex]                  = '\0';

        /* tab 打印指令列表或自动补全指令,属于内部操作指令 */
        ConCmdIn.Sta                                        = CON_CMD_TAB;

        ConCmdIn.Lock                                       = ETF_SET;
        /* 输入完成事件 */
        etf_event_post(&console_ps, ConsoleEvent, (void *)CONSOLE_EVENT_RX_DONE);
    } else if(0x1B == para){//-----------------------------处理[上][下]
        ConCmdIn.CombinationCount                           = 1;
    } else if((0x5B == para) && (1 == ConCmdIn.CombinationCount) ){
        ConCmdIn.CombinationCount                           = 2;
    } else if((0x41 == para) && (2 == ConCmdIn.CombinationCount) ){
        ConCmdIn.Sta                                        = CON_CMD_UP;
        ConCmdIn.Lock                                       = ETF_SET;
        /* 输入完成事件 */
        etf_event_post(&console_ps, ConsoleEvent, (void *)CONSOLE_EVENT_RX_DONE);
    } else if((0x42 == para) && (2 == ConCmdIn.CombinationCount) ){
        ConCmdIn.Sta                                        = CON_CMD_DOWN;
        ConCmdIn.Lock                                       = ETF_SET;
        /* 输入完成事件 */
        etf_event_post(&console_ps, ConsoleEvent, (void *)CONSOLE_EVENT_RX_DONE);
    } else {
        if(CMD_IN_ARR_SIZE > ConCmdIn.LastIndex){
            ConCmdIn.LastIndex++;
            ConCmdIn.Index++;
        }
        print_flag                                          = 1;
    }

    if( (0 != ConCmdIn.CombinationCount)&&(0x1B != para)&&(0x5B != para)&&(0x41 != para)&&(0x42 != para) ){
        ConCmdIn.CombinationCount                           = 0;
    } 

  
    if(1 == print_flag){
        //-----------------------------打印到屏幕，回显
        etf_device_write(Device, 0, (void *)&para, 1);
    }
}

/**
 *  命令行打印
 *
 *@param :  str：要打印的字符串；
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
void ComCmd_CmdLine(char *str){
    etf_device_write(ConsoleDevHanld, 0, (void *)"\033[40;32m", etf_strlen("\033[40;32m"));
    etf_device_write(ConsoleDevHanld, 0, (void *)str, etf_strlen(str));
    etf_device_write(ConsoleDevHanld, 0, (void *)"\033[0m", etf_strlen("\033[0m"));
}


/**
 *  把接收指令的一维素组按分隔符存储到二维素组；
 *
 *@param :  cmdstr          ：需要分析的字符串一维素组；
 *          AnalysisCmd     ：分析完存放的二维素组
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
void ConCmd_CmdAnalysis(char *cmdstr, con_cmd_analysis *AnalysisCmd){
    char                        *str1;
    etf_uint8_t                 i, cmd_len;
  
    str1                                                    = cmdstr;
    AnalysisCmd->argc                                       = 0;
    for(i = 0; CONFIG_CONSOLE_CMD_PARA_SIZE > i; i++){
        /* 复制指令 */
        cmd_len                                             = etf_strlench(str1, ' ');
        etf_strncpy(AnalysisCmd->CmdIn[i], str1, cmd_len);
        AnalysisCmd->CmdIn[i][cmd_len]                      = '\0';
        /* 移动到下一个分割点 */
        str1                                                = str1 + cmd_len;
        AnalysisCmd->argc++;
        if(' ' == *str1){
            str1++;
        } else if('\0' == *str1){
            break;
        }
    }
}

/* ************************************************************* **
 * 函数名称：int ConCmd_Pro(CON_CMD_IN_T *pConCmdIn)
 * 函数功能：指令处理函数
 * 入口参数：pConCmdIn：指令结构
 * 出口参数：无
** ************************************************************* */
etf_int32_t ConCmd_Pro(con_cmd_in *pConCmdIn){
    etf_uint16_t                i = 0, k = 0;
    char                        *str_tab                    = NULL;
    etf_uint16_t                len_tab                     = 0;
    etf_uint8_t                 ConCmdInRestFlag            = 1;

    pConCmdIn->Index                                        = 0;
  
    if(CON_CMD_TAB == pConCmdIn->Sta){
        /* ------------------------TAB指令列表打印------------------------ */
        if(0 == etf_strlen(pConCmdIn->CmdIn)){
            etf_device_write(ConsoleDevHanld, 0, (void *)"\r\n", 2);
            /* 内部tab指令，打印指令列表 */
            ConCmd_Help(0, NULL);
        } else {
            /* ------------------------处理TAB补全------------------------ */
            for(i = 0; NULL != ConCmdTable[i]; i++){
                if(!etf_strncmp(ConCmdTable[i]->Cmd, pConCmdIn->CmdIn, pConCmdIn->LastIndex)){
          
                    /* 匹配到指令，打印输出 */
                    etf_device_write(ConsoleDevHanld, 0, (void *)"\r\n", 2);
                    etf_device_write(ConsoleDevHanld, 0, (void *)(ConCmdTable[i]->Cmd), etf_strlen(ConCmdTable[i]->Cmd));
        
                    if(NULL == str_tab){
                    /* 指向当前匹配到的指令 */
                        str_tab                             = ConCmdTable[i]->Cmd;
                    } else {
                        if(0 == len_tab){
                            /* 查找到多个匹配，计算查找的的这两个匹配长度 */
                            len_tab                         = etf_strstrlen(str_tab, ConCmdTable[i]->Cmd);
                        } else {
                            /* 找出匹配最少的长度 */
                            if(etf_strstrlen(str_tab, ConCmdTable[i]->Cmd) < len_tab){
                                /* 指向当前这个最少的匹配度的指令 */
                                str_tab                     = ConCmdTable[i]->Cmd;
                                len_tab                     = etf_strstrlen(str_tab, ConCmdTable[i]->Cmd);
                            }
                        }
                    }
          
                }
            }
      
            if(NULL == str_tab){
                /* 未匹配到 */
                pConCmdIn->Index                            = pConCmdIn->LastIndex;
                pConCmdIn->Sta                              = CON_CMD_NO_ERR;
                pConCmdIn->Lock                             = ETF_RESET;
            } else {
                /* 匹配到指令，执行 */
                if(0 != len_tab){
                    /* 有多个匹配，只打印输出相同的部分 */
                    etf_strncpy(pConCmdIn->CmdIn, str_tab, len_tab);
                    pConCmdIn->CmdIn[len_tab]               = '\0';
                } else {
                    /* 只有一个匹配，打印完整指令 */
                    etf_strncpy(pConCmdIn->CmdIn, str_tab, CMD_IN_ARR_SIZE);
                }
                pConCmdIn->Sta                              = CON_CMD_NO_ERR;
                pConCmdIn->CombinationCount                 = 0;
                pConCmdIn->LastIndex                        = etf_strlen(pConCmdIn->CmdIn);
                pConCmdIn->Index                            = pConCmdIn->LastIndex;
                pConCmdIn->Lock                             = ETF_RESET;

                ComCmd_CmdLine("\r\ncmd>>");
                /* 打印匹配到的指令 */
                etf_device_write(ConsoleDevHanld, 0, (void *)(pConCmdIn->CmdIn), pConCmdIn->LastIndex);

            }
            /* 不复位指令输入结构体 */
            ConCmdInRestFlag                                = 0;
        }
    } else if( (CON_CMD_UP == pConCmdIn->Sta) || (CON_CMD_DOWN == pConCmdIn->Sta) ){
        /* ------------------------历史指令查询------------------------ */
        for(i = 0; i < pConCmdIn->LastIndex; i++){
            etf_device_write(ConsoleDevHanld, 0, (void *)"\b \b", 3);
        }

        if(CON_CMD_UP == pConCmdIn->Sta){
            /* 上一个历史指令 */
            if(0 != ConCmdInHistory.Index){
                ConCmdInHistory.Index--;
            }
        } else if(CON_CMD_DOWN == pConCmdIn->Sta){
            /* 下一个历史指令 */
            if(ConCmdInHistory.Top > ConCmdInHistory.Index){
                ConCmdInHistory.Index++;
            }
        }
    
        if(ConCmdInHistory.Top > ConCmdInHistory.Index){
            *pConCmdIn                                      = ConCmdInHistory.ConCmdIn[ConCmdInHistory.Index];
            /* 恢复历史指令输出到控制台 */
            etf_device_write(ConsoleDevHanld, 0, (void *)pConCmdIn->CmdIn, etf_strlen(pConCmdIn->CmdIn));
        } else {
            etf_strncpy(pConCmdIn->CmdIn, "\0", 1);
            pConCmdIn->LastIndex                            = 0;
            pConCmdIn->Index                                = 0;
            pConCmdIn->CombinationCount                     = 0;
            pConCmdIn->Lock                                 = ETF_RESET;
            pConCmdIn->Sta                                  = CON_CMD_NO_ERR;
        }
        /* 不复位指令输入结构体 */
        ConCmdInRestFlag                                    = 0;
    } else if(CON_CMD_NO_ERR == pConCmdIn->Sta){
        /* ------------------------指令匹配并执行指令------------------------ */
        if(0 != pConCmdIn->LastIndex){
            ConCmd_CmdAnalysis(pConCmdIn->CmdIn, &AnalysisCmd);
            for(i = 0; NULL != ConCmdTable[i]; i++){
                if(!etf_strncmp(ConCmdTable[i]->Cmd, AnalysisCmd.CmdIn[0], CONFIG_CONSOLE_CMD_SIZE)){
                    /* 匹配到指令，执行 */
                    ConCmdTable[i]->Fun(AnalysisCmd.argc, &AnalysisCmd);
                    break;
                }
            }
            /* 未匹配到指令输出提示 */
            if(NULL == ConCmdTable[i]){
                ComCmd_CmdLine("cmd not found.\r\n");
            }
        }
        /* ------------------------记录历史指令------------------------ */
        if(0 != pConCmdIn->LastIndex){
            if(0 == ConCmdInHistory.Top){
                /* 历史指令链表为空，记录当前指令为历史指令 */
                k                                           = 1;
            } else if(0 != etf_strncmp(pConCmdIn->CmdIn, ConCmdInHistory.ConCmdIn[ConCmdInHistory.Top-1].CmdIn, CMD_IN_ARR_SIZE)){
                /* 对比当前指令与上一次指令是否一样，一样则不记录，不一样记录 */
                k                                           = 1;
            } else {
                k                                           = 0;
            }
            if(1 == k){
                /* 记录历史指令 */
                if(CONFIG_CONSOLE_CMD_HISTORY_NUM > ConCmdInHistory.Top){
                    ConCmdInHistory.ConCmdIn[ConCmdInHistory.Top]           = *pConCmdIn;
                    ConCmdInHistory.ConCmdIn[ConCmdInHistory.Top].Lock      = ETF_RESET;
                    ConCmdInHistory.Top++;
                } else {
                    for(i = 1; i < CONFIG_CONSOLE_CMD_HISTORY_NUM; i++){
                        ConCmdInHistory.ConCmdIn[i-1]                       = ConCmdInHistory.ConCmdIn[i];
                    }
                    ConCmdInHistory.ConCmdIn[i-1]                           = *pConCmdIn;
                    ConCmdInHistory.ConCmdIn[i-1].Lock                      = ETF_RESET;
                }
        
            }
            ConCmdInHistory.Index                                           = ConCmdInHistory.Top;
        }
    
    } else {
        ComCmd_CmdLine("cmd input error.\r\n");
    }

    /* ------------------------处理完毕，指令结构复位------------------------ */
    if(1 == ConCmdInRestFlag){
        pConCmdIn->Sta                                      = CON_CMD_NO_ERR;
        pConCmdIn->LastIndex                                = 0;
        pConCmdIn->Index                                    = 0;
        pConCmdIn->CombinationCount                         = 0;
        pConCmdIn->Lock                                     = ETF_RESET;

        ComCmd_CmdLine("cmd>>");
    }
  
    return 0;
}

/**
 *  控制台命令 version 处理函数
 *
 *@param :  argc：参数数目；
 *          argv：指令参数结构
 *
 *@return:  0：执行成功
 *
 *@note  : 
 *
 *
 */
etf_int32_t ConCmd_Versions(etf_int32_t argc, con_cmd_analysis *argv){
  etf_device_write(ConsoleDevHanld, 0, (void *)ConsoleVersion, etf_strlen(ConsoleVersion));
  return 0;
}


/**
 *  控制台命令 help 处理函数
 *
 *@param :  argc：参数数目；
 *          argv：指令参数结构
 *
 *@return:  0：执行成功
 *
 *@note  : 
 *
 *
 */
etf_int32_t ConCmd_Help(etf_int32_t argc, con_cmd_analysis *argv){
    etf_uint16_t                    i, j;
    char                            cmd_str[CONFIG_CONSOLE_CMD_SIZE+10];

    etf_device_write(ConsoleDevHanld, 0, (void *)"Commands:\r\n", etf_strlen("Commands:\r\n"));

    for(i = 0; NULL != ConCmdTable[i]; i++){
        etf_strncpy(cmd_str, ConCmdTable[i]->Cmd, CONFIG_CONSOLE_CMD_SIZE);
        j                                                   = etf_strlen(cmd_str);
        if(CONFIG_CONSOLE_CMD_SIZE+10 > j){
            for(;j < CONFIG_CONSOLE_CMD_SIZE+10; j++){
                cmd_str[j]                                  = ' ';
            }
            cmd_str[j]                                      = '\0';
        }

        etf_device_write(ConsoleDevHanld, 0, (void *)cmd_str, etf_strlen(cmd_str));
        etf_device_write(ConsoleDevHanld, 0, (void *)"-", 1);
        etf_device_write(ConsoleDevHanld, 0, (void *)ConCmdTable[i]->DesStr, etf_strlen(ConCmdTable[i]->DesStr));  
    }

    return 0;
}

etf_int32_t ConCmd_Reboot(etf_int32_t argc, con_cmd_analysis *argv){

    ETF_REBOOT();
    return 0;
}


etf_int32_t ConCmd_DeviceList(etf_int32_t argc, con_cmd_analysis *argv){

    static struct etf_object_information *      information = ETF_NULL;
    struct etf_list_node *                      node;
    etf_device_t                                node_device;
    
    information                                             = etf_object_get_information(ETF_Object_Class_Device);

    if(ETF_NULL == information){
        etf_device_write(ConsoleDevHanld, 0, (void *)"The list is empty\r\n", etf_strlen("The list is empty\r\n"));
        return 0;
    }

    etf_device_write(ConsoleDevHanld, 0, (void *)"device list [name---type---state]:\r\n\n", etf_strlen("device list [name---type---state]:\r\n\n"));

    if(!etf_list_isempty(&(information->object_run_list))){
        for(node = information->object_run_list.next; node != &(information->object_run_list); node = node->next){
            /* 获取节点对象 */
            node_device                                         = (etf_device_t)etf_list_entry(node, struct etf_object, list);

            /* 设备名 */
            etf_device_write(ConsoleDevHanld, 0, (void *)(node_device->parent.name), etf_strlen(node_device->parent.name));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 设备类型 */
            etf_device_write(ConsoleDevHanld, 0, (void *)(etf_device_class_type_table[node_device->type]), etf_strlen(etf_device_class_type_table[node_device->type]));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 设备状态 */
            if(ETF_DEVICE_OFLAG_OPEN & node_device->open_flag){
                /* 打开 */
                etf_device_write(ConsoleDevHanld, 0, (void *)"open", 4);
            } else {
                /* 关闭 */
                etf_device_write(ConsoleDevHanld, 0, (void *)"close", 5);
            }
            etf_device_write(ConsoleDevHanld, 0, (void *)"\r\n", 2);
        } 
    } else {
        etf_device_write(ConsoleDevHanld, 0, (void *)"The list is empty\r\n", etf_strlen("The list is empty\r\n"));
        return 0;
    }
    
    etf_device_write(ConsoleDevHanld, 0, (void *)"\n", 1);
    return 0;
}

etf_int32_t ConCmd_EventList(etf_int32_t argc, con_cmd_analysis *argv){

    static struct etf_object_information *      information = ETF_NULL;
    struct etf_list_node *                      node;
    etf_event_t                                 node_event;
    char                                        str[10];

    
    information                                             = etf_object_get_information(ETF_Object_Class_Event);

    if( ETF_NULL == information ){
        etf_device_write(ConsoleDevHanld, 0, (void *)"The list is empty\r\n", etf_strlen("The list is empty\r\n"));
        return 0;
    }

    etf_device_write(ConsoleDevHanld, 0, (void *)"event list [value---coroutine]:\r\n\n", etf_strlen("event list [value---coroutine]:\r\n\n"));

    if(!etf_list_isempty(&(information->object_run_list))){
        for(node = information->object_run_list.next; node != &(information->object_run_list); node = node->next){
            /* 获取节点对象 */
            node_event                                          = (etf_event_t)etf_list_entry(node, struct etf_object, list);

            /* 事件值 */
            etf_itoa( (etf_int32_t)(node_event->ev), str, 10);
            etf_device_write(ConsoleDevHanld, 0, (void *)str, etf_strlen(str));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 协程 */
            etf_device_write(ConsoleDevHanld, 0, (void *)(node_event->p->parent.name), etf_strlen(node_event->p->parent.name));

            etf_device_write(ConsoleDevHanld, 0, (void *)"\r\n", 2);
        }
    } else {
        etf_device_write(ConsoleDevHanld, 0, (void *)"The list is empty\r\n", etf_strlen("The list is empty\r\n"));
        return 0;
    }
    etf_device_write(ConsoleDevHanld, 0, (void *)"\n", 1);
    
    return 0;
}

etf_int32_t ConCmd_TimerList(etf_int32_t argc, con_cmd_analysis *argv){

    static struct etf_object_information *      information = ETF_NULL;
    struct etf_list_node *                      node;
    etf_timer_t                                 node_timer;
    char                                        str[11];
    etf_uint8_t                                 list_empty_flag = 0;

    
    information                                             = etf_object_get_information(ETF_Object_Class_Timer);

    if(ETF_NULL == information){
        etf_device_write(ConsoleDevHanld, 0, (void *)"The list is empty\r\n", etf_strlen("The list is empty\r\n"));
        return 0;
    }

    etf_device_write(ConsoleDevHanld, 0, (void *)"timer list [name---type---state---callback---coroutine]:\r\n\n", etf_strlen("timer list [name---type---state---callback---coroutine]:\r\n\n"));

    if( !etf_list_isempty(&(information->object_run_list)) ){
        list_empty_flag                                         = 1;
        for(node = information->object_run_list.next; node != &(information->object_run_list); node = node->next){
            /* 获取节点对象 */
            node_timer                                          = (etf_timer_t)etf_list_entry(node, struct etf_object, list);

            /* 定时器名 */
            etf_device_write(ConsoleDevHanld, 0, (void *)(node_timer->parent.name), etf_strlen(node_timer->parent.name));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 类型 */
            if(TIMER_TYPE_ONE == node_timer->type){
                etf_strncpy(str, "one", 10);
            } else if(TIMER_TYPE_PERIOD == node_timer->type){
                etf_strncpy(str, "period", 10);
            } else {
                etf_strncpy(str, "error", 10);
            }
            etf_device_write(ConsoleDevHanld, 0, (void *)str, etf_strlen(str));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 状态 */
            etf_strncpy(str, "running", 10);
            etf_device_write(ConsoleDevHanld, 0, (void *)str, etf_strlen(str));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 回调函数 */
            if(ETF_NULL == node_timer->c_callback){
                etf_strncpy(str, "null", 10);
            } else {
                etf_strncpy(str, "have", 10);
            }
            etf_device_write(ConsoleDevHanld, 0, (void *)str, etf_strlen(str));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 关联协程名 */
            if(ETF_NULL == node_timer->e_callback){
                etf_device_write(ConsoleDevHanld, 0, (void *)"null", etf_strlen("null"));
            } else {
                etf_device_write(ConsoleDevHanld, 0, (void *)(node_timer->e_callback->parent.name), etf_strlen(node_timer->e_callback->parent.name));  
            }

            etf_device_write(ConsoleDevHanld, 0, (void *)"\r\n", 2);
        }
    }

    if( !etf_list_isempty(&(information->object_suspend_list)) ){
        list_empty_flag                                         = 1;
        for(node = information->object_suspend_list.next; node != &(information->object_suspend_list); node = node->next){
            /* 获取节点对象 */
            node_timer                                          = (etf_timer_t)etf_list_entry(node, struct etf_object, list);

            /* 定时器名 */
            etf_device_write(ConsoleDevHanld, 0, (void *)(node_timer->parent.name), etf_strlen(node_timer->parent.name));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 类型 */
            if(TIMER_TYPE_ONE == node_timer->type){
                etf_strncpy(str, "one", 10);
            } else if(TIMER_TYPE_PERIOD == node_timer->type){
                etf_strncpy(str, "period", 10);
            } else {
                etf_strncpy(str, "error", 10);
            }
            etf_device_write(ConsoleDevHanld, 0, (void *)str, etf_strlen(str));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 状态 */
            etf_strncpy(str, "suspended", 10);
            etf_device_write(ConsoleDevHanld, 0, (void *)str, etf_strlen(str));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 回调函数 */
            if(ETF_NULL == node_timer->c_callback){
                etf_strncpy(str, "null", 10);
            } else {
                etf_strncpy(str, "have", 10);
            }
            etf_device_write(ConsoleDevHanld, 0, (void *)str, etf_strlen(str));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 关联协程名 */
            if(ETF_NULL == node_timer->e_callback){
                etf_device_write(ConsoleDevHanld, 0, (void *)"null", etf_strlen("null"));
            } else {
                etf_device_write(ConsoleDevHanld, 0, (void *)(node_timer->e_callback->parent.name), etf_strlen(node_timer->e_callback->parent.name));  
            }

            etf_device_write(ConsoleDevHanld, 0, (void *)"\r\n", 2);
        }
    }

    if(0 == list_empty_flag){
        etf_device_write(ConsoleDevHanld, 0, (void *)"The list is empty\r\n", etf_strlen("The list is empty\r\n"));
        return 0;
    }
    
    etf_device_write(ConsoleDevHanld, 0, (void *)"\n", 1);
    
    return 0;
}

etf_int32_t ConCmd_CoroutineList(etf_int32_t argc, con_cmd_analysis *argv){

    static struct etf_object_information *      information = ETF_NULL;
    struct etf_list_node *                      node;
    etf_co_tcb_t                                node_coroutine;
    char                                        str[11];
    etf_uint8_t                                 list_empty_flag = 0;

    
    information                                             = etf_object_get_information(ETF_Object_Class_Coroutine);

    if(ETF_NULL == information){
        etf_device_write(ConsoleDevHanld, 0, (void *)"The list is empty\r\n", etf_strlen("The list is empty\r\n"));
        return 0;
    }

    etf_device_write(ConsoleDevHanld, 0, (void *)"coroutine list [name---needspoll---state]:\r\n\n", etf_strlen("coroutine list [name---needspoll---state]:\r\n\n"));

    if( !etf_list_isempty(&(information->object_run_list)) ){
        list_empty_flag                                         = 1;
        for(node = information->object_run_list.next; node != &(information->object_run_list); node = node->next){
            /* 获取节点对象 */
            node_coroutine                                      = (etf_co_tcb_t)etf_list_entry(node, struct etf_object, list);

            /* 协程名 */
            etf_device_write(ConsoleDevHanld, 0, (void *)(node_coroutine->parent.name), etf_strlen(node_coroutine->parent.name));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 轮询请求*/
            etf_itoa( (etf_int32_t)(node_coroutine->needspoll), str, 10);
            etf_device_write(ConsoleDevHanld, 0, (void *)str, etf_strlen(str));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 状态 */
            if(ETF_PROCESS_STATE_RUNNING == node_coroutine->state){
                etf_strncpy(str, "running", 10);
            } else if(ETF_PROCESS_STATE_CALLED == node_coroutine->state){
                etf_strncpy(str, "called", 10);
            } else {
                etf_strncpy(str, "suspended", 10);
            }
            etf_device_write(ConsoleDevHanld, 0, (void *)str, etf_strlen(str));
            etf_device_write(ConsoleDevHanld, 0, (void *)"\r\n", 2);
        }
    }

    if( !etf_list_isempty(&(information->object_suspend_list)) ){
        list_empty_flag                                         = 1;
        for(node = information->object_suspend_list.next; node != &(information->object_suspend_list); node = node->next){
            /* 获取节点对象 */
            node_coroutine                                      = (etf_co_tcb_t)etf_list_entry(node, struct etf_object, list);

            /* 协程名 */
            etf_device_write(ConsoleDevHanld, 0, (void *)(node_coroutine->parent.name), etf_strlen(node_coroutine->parent.name));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 轮询请求*/
            etf_itoa( (etf_int32_t)(node_coroutine->needspoll), str, 10);
            etf_device_write(ConsoleDevHanld, 0, (void *)str, etf_strlen(str));
            etf_device_write(ConsoleDevHanld, 0, (void *)"---", 3);
            /* 状态 */
            if(ETF_PROCESS_STATE_RUNNING == node_coroutine->state){
                etf_strncpy(str, "running", 10);
            } else if(ETF_PROCESS_STATE_CALLED == node_coroutine->state){
                etf_strncpy(str, "called", 10);
            } else {
                etf_strncpy(str, "suspended", 10);
            }
            etf_device_write(ConsoleDevHanld, 0, (void *)str, etf_strlen(str));
            etf_device_write(ConsoleDevHanld, 0, (void *)"\r\n", 2);
        }
    }

    if(0 == list_empty_flag){
        etf_device_write(ConsoleDevHanld, 0, (void *)"The list is empty\r\n", etf_strlen("The list is empty\r\n"));
        return 0;
    }
    
    etf_device_write(ConsoleDevHanld, 0, (void *)"\n", 1);
    
    return 0;
}

#endif

